package com.smile.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
//import com.smile.api.AirlineApi;
import com.smile.api.AirlineDeviceApi;
import com.smile.api.AirportApi;
import com.smile.api.InspectionTaskApi;
import com.smile.api.OrganizationApi;
import com.smile.commons.error.ErrorCodeUtil;
import com.smile.commons.page.MyBatisPlusPageConverter;
import com.smile.commons.page.R;
import com.smile.mapper.*;
import com.smile.model.domain.*;
import com.smile.model.dto.request.GetAirlineByAirlineCodeRequestDTO;
import com.smile.model.dto.request.GetInspectionTaskByFlightIdRequestDTO;
import com.smile.model.dto.request.GetInspectionTaskDetailRequestDTO;
import com.smile.model.dto.request.GetInspectionTaskListRequestDTO;
import com.smile.model.request.GetAirlineByAirlineCodeRequest;
import com.smile.model.response.GetAirlineByAirlineCodeResponse;
import com.smile.model.response.GetAirportByIdsResponse;
import com.smile.model.response.response.GetAirlineByAirlineCodeResponseDTO;
import com.smile.model.response.response.GetInspectionTaskByFlightIdResponseDTO;
import com.smile.model.response.response.GetInspectionTaskDetailResponseDTO;
import com.smile.model.response.response.GetInspectionTaskListResponseDTO;
import com.smile.model.request.GetAirportByIdRequest;
import com.smile.model.response.GetAirportByIdResponse;
import com.smile.service.AirlineService;
import com.smile.service.InspectionTaskService;
import lombok.extern.slf4j.Slf4j;
import org.dromara.dynamictp.core.executor.DtpExecutor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.time.Duration;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.stream.Collectors;

@Slf4j
@Service
public class InspectionTaskServiceImpl implements InspectionTaskService {

    @Autowired
    private InspectionTaskMapper inspectionTaskMapper;

    @Autowired
    private AirportApi airportApi;

    @Autowired
    private OrganizationMapper organizationMapper;

    @Autowired
    private AirLineMapper airlineMapper;

    @Autowired
    private AirLineMapper airLineMapper;

    @Autowired
    private DtpExecutor dtpExecutor0;

    @Autowired
    private WayPointTaskInfoMapper wayPointTaskInfoMapper;

    @Value("${xxl.job.admin.addresses}")
    private String xxlJobAdminAddresses;
    @Autowired
    private AirlineService airlineService;
    @Autowired
    private AirportMapper airportMapper;


    @Override
    public Page<GetInspectionTaskListResponseDTO> getInspectionTaskList(GetInspectionTaskListRequestDTO getInspectionTaskListRequestDTO) {
        Long startTime = System.currentTimeMillis();
        System.out.println("开始查询巡检任务列表,当前的时间为:" + LocalDateTime.now());
        QueryWrapper<FeisuanInspectionTask> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq(StrUtil.isNotBlank(getInspectionTaskListRequestDTO.getPlanName()), "plan_name", getInspectionTaskListRequestDTO.getPlanName());
        queryWrapper.eq(ObjectUtil.isNotNull(getInspectionTaskListRequestDTO.getStatus()), "status", getInspectionTaskListRequestDTO.getStatus());
        queryWrapper.orderByDesc("plan_start_time");
        System.out.println("开始查询巡检任务列表数据库操作,当前的时间为:" + LocalDateTime.now());
        Page<FeisuanInspectionTask> feisuanInspectionTaskPage = inspectionTaskMapper.selectPage(new Page<>(getInspectionTaskListRequestDTO.getCurrentPage(), getInspectionTaskListRequestDTO.getPageSize()), queryWrapper);
        System.out.println("巡检列表数据库查询完成");

        List<Long> collect1 = feisuanInspectionTaskPage.getRecords().stream().map(i -> {
            return i.getAirlineId().longValue();
        }).collect(Collectors.toList());

//        R<Map<Long, GetAirportByIdsResponse>> airportByIds = airportApi.getAirportByIds(collect1);


        List<GetInspectionTaskListResponseDTO> collect = feisuanInspectionTaskPage.getRecords().stream().map(i -> {
            GetInspectionTaskListResponseDTO responseDTO = new GetInspectionTaskListResponseDTO();
            responseDTO.setId(i.getId());
            responseDTO.setPlanName(i.getPlanName());
            responseDTO.setStatus(i.getStatus());
            responseDTO.setStartTime(i.getPlanStartTime());
            responseDTO.setEndTime(i.getEndTime());
            responseDTO.setExecuteTime(i.getStartTime());
            GetAirportByIdRequest getAirportByIdRequest = new GetAirportByIdRequest();
            getAirportByIdRequest.setId(i.getAirportId());
            FeisuanAirport feisuanAirport = airportMapper.selectById(i.getAirportId());
            if (ObjectUtil.isNotNull(feisuanAirport)) {
                responseDTO.setAirportName(feisuanAirport.getAirportName());
            }
            if (i.getErrorCode() != null) {
                if (i.getErrorCode() == 0) {
                    responseDTO.setErrInfo("执行成功");
                } else {
                    if (ObjectUtil.isNotNull(i.getErrorCode())) {

                        responseDTO.setErrInfo(ErrorCodeUtil.getErrorDescription(i.getErrorCode()));
                    } else {
                        responseDTO.setErrInfo(i.getErrorCode().toString());
                    }
                    if (i.getErrorCode() == 1) {
                        responseDTO.setErrInfo(i.getErrorMessage());
                    }
                }
            } else {
                responseDTO.setErrInfo("");
            }
            if(i.getStatus() == 1){
                Duration duration = Duration.between(i.getPlanStartTime(), LocalDateTime.now());
                System.out.println(duration.getSeconds());
                if(duration.getSeconds() > 20){
                    responseDTO.setStatus(5);
                    responseDTO.setErrInfo("超时未执行");
                }
            }
            //判断


            //TODO这里尽量不要在循环中使用数据库操作，可以优化的
            FeisuanAirline feisuanAirline = airlineMapper.selectById(i.getAirlineId());
            if (ObjectUtil.isNotNull(feisuanAirline)) {
                responseDTO.setAirlineName(feisuanAirline.getAirlineName());
            }

//            if (ObjectUtil.isNotNull(airportByIds) && ObjectUtil.isNotNull(airportByIds.getData())
//                    && ObjectUtil.isNotNull(airportByIds.getData().get(i.getAirlineId()))) {
//                responseDTO.setAirportName(airportByIds.getData().get(i.getAirlineId()).getAirportName());
//            }

//            R<GetAirportByIdResponse> airportById = airportApi.getAirportById(getAirportByIdRequest);
//            if (ObjectUtil.isNotNull(airportById) && ObjectUtil.isNotNull(airportById.getData())) {
//                responseDTO.setAirportName(airportById.getData().getAirportName());
//            }
            Future<?> submit = dtpExecutor0.submit(() -> {
                if (i.getExecuteType() == 3) {
                    //0. 指定某个星期几 1. 指定某个月多少号 2 隔多少天执行一次
                    if (i.getJobType() == 0) {
                        String[] week = {"星期天", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六"};
                        responseDTO.setTaskRule("每隔" + i.getWeeks() + "个星期的" + week[i.getWeek()] + "执行");
                    } else if (i.getJobType() == 1) {
                        responseDTO.setTaskRule("每隔" + i.getMonths() + "个月的第" + i.getDay() + "天执行");
                    } else if (i.getJobType() == 2) {
                        responseDTO.setTaskRule("每隔" + i.getDays() + "天执行");
                    }
                } else {
                    responseDTO.setTaskRule("-");
                }

            });
            try {
                submit.get();
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            } catch (ExecutionException e) {
                throw new RuntimeException(e);
            }


            return responseDTO;
        }).collect(Collectors.toList());

        Page<GetInspectionTaskListResponseDTO> getInspectionTaskListResponseDTOPage = MyBatisPlusPageConverter.convertPage(feisuanInspectionTaskPage, GetInspectionTaskListResponseDTO.class);
        getInspectionTaskListResponseDTOPage.setRecords(collect);
        Long endTime = System.currentTimeMillis();
        log.info("巡检任务列表,查询的时间为:" + (endTime - startTime) + "ms 当前时间为:" + LocalDateTime.now());

        return getInspectionTaskListResponseDTOPage;
    }


    @Override
    public Boolean cancelExecute(GetInspectionTaskDetailRequestDTO getInspectionTaskListRequestDTO) {
        FeisuanInspectionTask feisuanInspectionTask = inspectionTaskMapper.selectById(getInspectionTaskListRequestDTO.getId());
//        QueryWrapper<FeisuanInspectionTask> queryWrapper = new QueryWrapper<>();

        if (ObjectUtil.isNotNull(feisuanInspectionTask)) {
            if (feisuanInspectionTask.getStatus() == 1) {
                feisuanInspectionTask.setStatus(3);
                inspectionTaskMapper.updateById(feisuanInspectionTask);
                HttpUtil.get(xxlJobAdminAddresses + "/jobinfo/remove?id=" + feisuanInspectionTask.getJobId());
                return Boolean.TRUE;
            } else {
                throw new RuntimeException("任务非待执行状态");
            }
        } else {
            return Boolean.FALSE;
        }
    }

    @Override
    public GetInspectionTaskDetailResponseDTO getInspectionTaskDetail(GetInspectionTaskDetailRequestDTO getInspectionTaskListRequestDTO) {
        FeisuanInspectionTask feisuanInspectionTask = inspectionTaskMapper.selectById(getInspectionTaskListRequestDTO.getId());
        GetInspectionTaskDetailResponseDTO getInspectionTaskDetailResponseDTO = BeanUtil.copyProperties(feisuanInspectionTask, GetInspectionTaskDetailResponseDTO.class);
//        GetOrganizationByIdRequest getOrganizationByIdRequest = new GetOrganizationByIdRequest();
////        getOrganizationByIdRequest.setId(feisuanInspectionTask.get);


        GetAirportByIdRequest getAirportByIdRequest = new GetAirportByIdRequest();
        getAirportByIdRequest.setId(feisuanInspectionTask.getAirportId());
//        feisuanInspectionTask.getOrganizationId();

//        SmilePlusOrganization smilePlusOrganization = organizationMapper.selectById(feisuanInspectionTask.getOrganizationId());
        // 获取组织机构名称（包含删除了的组织名称）
        SmilePlusOrganization smilePlusOrganization = organizationMapper.getById(feisuanInspectionTask.getOrganizationId());

        if (ObjectUtil.isNotNull(smilePlusOrganization)) {
            getInspectionTaskDetailResponseDTO.setOrganizationName(smilePlusOrganization.getOrganizationName());
        }
        FeisuanAirline feisuanAirline = airlineMapper.selectById(feisuanInspectionTask.getAirlineId());
        if (ObjectUtil.isNotNull(feisuanAirline)) {
            getInspectionTaskDetailResponseDTO.setAirlineName(feisuanAirline.getAirlineName());
        }

        R<GetAirportByIdResponse> airportById = airportApi.getAirportById(getAirportByIdRequest);
        if (ObjectUtil.isNotNull(airportById) && ObjectUtil.isNotNull(airportById.getData())) {
            getInspectionTaskDetailResponseDTO.setAirportName(airportById.getData().getAirportName());
        }

        if (feisuanInspectionTask.getExecuteType() == 2) {
            //0. 指定某个星期几 1. 指定某个月多少号 2 隔多少天执行一次
            if (feisuanInspectionTask.getJobType() == 0) {
                String[] week = {"星期天", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六"};
                getInspectionTaskDetailResponseDTO.setTaskRule("每隔" + feisuanInspectionTask.getWeeks() + "个星期的" + week[feisuanInspectionTask.getWeek()] + "执行");
            } else if (feisuanInspectionTask.getJobType() == 1) {
                getInspectionTaskDetailResponseDTO.setTaskRule("每隔" + feisuanInspectionTask.getMonths() + "个月的第" + feisuanInspectionTask.getDay() + "天执行");
            } else if (feisuanInspectionTask.getJobType() == 2) {
                getInspectionTaskDetailResponseDTO.setTaskRule("每隔" + feisuanInspectionTask.getDays() + "天执行");
            }
        } else {
            getInspectionTaskDetailResponseDTO.setTaskRule("-");
        }

        String flightId = feisuanInspectionTask.getFlightId();
        if (StrUtil.isNotBlank(flightId)) {
            QueryWrapper<FeisuanWayPointTaskInfo> feisuanWayPointTaskInfoQueryWrapper = new QueryWrapper<>();
            feisuanWayPointTaskInfoQueryWrapper.eq("flight_id", flightId);
            List<FeisuanWayPointTaskInfo> feisuanWayPointTaskInfos = wayPointTaskInfoMapper.selectList(feisuanWayPointTaskInfoQueryWrapper);
            List<GetInspectionTaskDetailResponseDTO.Task> collect = feisuanWayPointTaskInfos.stream().map(i -> {
                GetInspectionTaskDetailResponseDTO.Task task = new GetInspectionTaskDetailResponseDTO.Task();
                task.setExecuteTime(i.getCreateTime().toLocalTime());
                task.setProcessName(i.getProcessName());
                return task;
            }).collect(Collectors.toList());


            getInspectionTaskDetailResponseDTO.setTaskList(collect);
        }

        return getInspectionTaskDetailResponseDTO;
    }

    @Override
    public GetInspectionTaskByFlightIdResponseDTO getInspectionTaskByFlightId(GetInspectionTaskByFlightIdRequestDTO getInspectionTaskByFlightIdRequestDTO) {
        String flightId = getInspectionTaskByFlightIdRequestDTO.getFlightId();
        QueryWrapper<FeisuanInspectionTask> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("flight_id", flightId);
        List<FeisuanInspectionTask> feisuanInspectionTasks = inspectionTaskMapper.selectList(queryWrapper);
        if (CollectionUtil.isNotEmpty(feisuanInspectionTasks)) {
            FeisuanInspectionTask feisuanInspectionTask = feisuanInspectionTasks.get(0);
            if (ObjectUtil.isNotNull(feisuanInspectionTask.getAirlineCode())) {
                GetAirlineByAirlineCodeRequest getAirlineByAirlineCodeRequest = new GetAirlineByAirlineCodeRequest();
                getAirlineByAirlineCodeRequest.setAirlineCode(feisuanInspectionTask.getAirlineCode());
                GetAirlineByAirlineCodeRequestDTO getAirlineByAirlineCodeRequestDTO = new GetAirlineByAirlineCodeRequestDTO();
                getAirlineByAirlineCodeRequestDTO.setAirlineCode(feisuanInspectionTasks.get(0).getAirlineCode());
                GetAirlineByAirlineCodeResponseDTO getAirlineByAirlineCodeResponseDTO = airlineService.getAirlineByAirlineCode(getAirlineByAirlineCodeRequestDTO);
//                R<GetAirlineByAirlineCodeResponse> airlineByAirlineCode = airlineApi.getAirlineByAirlineCode(getAirlineByAirlineCodeRequest);
                GetInspectionTaskByFlightIdResponseDTO getInspectionTaskByFlightIdResponseDTO = new GetInspectionTaskByFlightIdResponseDTO();
                getInspectionTaskByFlightIdResponseDTO.setEtag(getAirlineByAirlineCodeResponseDTO.getETag());
                getInspectionTaskByFlightIdResponseDTO.setUrl(getAirlineByAirlineCodeResponseDTO.getAirlineUrl());
                Long airportId = getAirlineByAirlineCodeResponseDTO.getAirportId();

                GetAirportByIdRequest getAirportByIdRequest = new GetAirportByIdRequest();
                getAirportByIdRequest.setId(airportId);
                R<GetAirportByIdResponse> airportById = airportApi.getAirportById(getAirportByIdRequest);
                if (ObjectUtil.isNotNull(airportById) && ObjectUtil.isNotNull(airportById.getData())) {
                    getInspectionTaskByFlightIdResponseDTO.setGateway(airportById.getData().getGateway());
                }
                return getInspectionTaskByFlightIdResponseDTO;
            }

            Integer airlineId = feisuanInspectionTask.getAirlineId();
            FeisuanAirline feisuanAirline = airlineMapper.selectById(airlineId);
            GetInspectionTaskByFlightIdResponseDTO getInspectionTaskByFlightIdResponseDTO = new GetInspectionTaskByFlightIdResponseDTO();
            getInspectionTaskByFlightIdResponseDTO.setEtag(feisuanAirline.getETag());
            getInspectionTaskByFlightIdResponseDTO.setUrl(feisuanAirline.getAirlineUrl());
            Long airportId = feisuanInspectionTasks.get(0).getAirportId();

            GetAirportByIdRequest getAirportByIdRequest = new GetAirportByIdRequest();
            getAirportByIdRequest.setId(airportId);
            R<GetAirportByIdResponse> airportById = airportApi.getAirportById(getAirportByIdRequest);
            if (ObjectUtil.isNotNull(airportById) && ObjectUtil.isNotNull(airportById.getData())) {
                getInspectionTaskByFlightIdResponseDTO.setGateway(airportById.getData().getGateway());
            }

            return getInspectionTaskByFlightIdResponseDTO;
        }
        return null;
    }

    /**
     * 更新巡检任务状态
     * @param organizationId 组织id
     * @param status 1-待执行 2-执行中 3-已取消 4-已完成
     */
    @Override
    public void updateTaskStatus(Long organizationId, Integer status) {

        // 该组织下所有巡检任务
        List<FeisuanInspectionTask> feisuanInspectionTasks = inspectionTaskMapper.selectList(new LambdaQueryWrapper<FeisuanInspectionTask>() {{
            eq(FeisuanInspectionTask::getOrganizationId, organizationId);
            eq(FeisuanInspectionTask::getStatus, 1);
        }});
//        HttpUtil.get(xxlJobAdminAddresses + "/jobinfo/remove?id=" + feisuanInspectionTask.getJobId());
        if (CollectionUtil.isNotEmpty(feisuanInspectionTasks)) {
            inspectionTaskMapper.update(new FeisuanInspectionTask() {{
                // 状态 1-待执行 2-执行中 3-已取消 4-已完成
                setStatus(3);
            }}, new LambdaQueryWrapper<FeisuanInspectionTask>() {{
                eq(FeisuanInspectionTask::getOrganizationId, organizationId);
                eq(FeisuanInspectionTask::getStatus, 1);
            }});
            for(FeisuanInspectionTask feisuanInspectionTask : feisuanInspectionTasks) {
                HttpUtil.get(xxlJobAdminAddresses + "/jobinfo/remove?id=" + feisuanInspectionTask.getJobId());
            }
        }

    }

}
